package com.atlassian.license.decoder;
import com.atlassian.extras.common.log.Logger;

import com.atlassian.extras.decoder.v2.Version2LicenseDecoder;

import com.atlassian.license.License;
import com.atlassian.license.LicenseException;
import com.atlassian.license.LicenseManager;
import com.atlassian.license.LicensePair;
import com.atlassian.license.LicenseType;
import com.atlassian.license.LicenseUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.Properties;
import java.util.StringTokenizer;

public class LicenseDecoder {
    private static final Logger.Log log = Logger.getInstance(LicenseDecoder.class);

    public static final String DURATION_PREFIX = "Duration:";

    public static final String JIRA_APPLICATION_NAME = "JIRA";

    public static final String CONF_APPLICATION_NAME = "CONFLUENCE";

    public static License getLicense(LicensePair pair, String applicationName) {
        try {
            return loadLicense(pair, getPublicKey(applicationName), applicationName);
        } catch (LicenseException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static boolean isValid(LicensePair pair, String applicationName) {
        return (getLicense(pair, applicationName) != null);
    }

    private static PublicKey getPublicKey(String applicationName) throws LicenseException {
        String publicKeyFileName = getPublicKeyFilename(applicationName);
        if (publicKeyFileName == null || "".equals(publicKeyFileName)) {
            throw new LicenseException("The filename for the public key is null. This must be set before a public key can be located.");
        }
        try {
            return loadPublicKeyFromFile(publicKeyFileName);
        } catch (Exception e) {
            log.error("Exception looking up public key: " + e.getMessage(), e);
            throw new LicenseException("Exception getting verification from file - possible classloader problem, or corrupt JIRA installation ");
        }
    }

    public static PublicKey loadPublicKeyFromFile(String publicKeyFileName) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        InputStream keyfis = null;
        ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
        if (contextLoader != null) {
            keyfis = contextLoader.getResourceAsStream(publicKeyFileName);
        }
        if (keyfis == null) {
            keyfis = LicenseDecoder.class.getClassLoader().getResourceAsStream(publicKeyFileName);
        }
        byte[] encKey = LicenseUtils.readKey(keyfis);
        keyfis.close();
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
        return keyFactory.generatePublic(pubKeySpec);
    }

    private static License loadLicense(LicensePair pair, PublicKey publicKey, String applicationName) {
        try {
            if (pair.isNG()) {
                return parseNewLicense(pair, applicationName);
            }
            return parseOldLicense(pair, publicKey, applicationName);
        } catch (Exception e) {
            log.error(e);
            return null;
        }
    }

    public static License parseOldLicense(LicensePair pair, PublicKey publicKey, String applicationName) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, LicenseException {
       return null;
    }

    private static License parseNewLicense(LicensePair pair, String applicationName) throws LicenseException {
      return null;
    }


    private static String getDecodedMessage(byte[] message) {
        try {
            return new String(message, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static boolean isValid(LicensePair pair, PublicKey publicKey, String applicationName) {
        return (loadLicense(pair, publicKey, applicationName) != null);
    }

    private static String getPublicKeyFilename(String applicationName) {
        return LicenseManager.getInstance().getLicenseTypeStore(applicationName).getPublicKeyFileName();
    }
}
